// all trax programs must include trax.hpp
#include "trax.hpp"
#include "Image.h"
#include "Vector3.h"
#include "Sphere.h"
#include "HitRecord.h"
#include "PinHoleCamera.h"
#include "Scene.h"
#include "Shader.h"
#include "AABBox.h"
#include "Unit_Test.h"
#include "atTriangle.h"
#include "RayTracer.h"

// "main" function is called "trax_main", returns void instead of int
void trax_main()
{
    using namespace AtomTrace;
	//Unit_test_Vector3();
    //Unit_test_BoxIntersection();
    //Unit_test_TriangleIntersection();
    //Unit_test_BVH_Stack();
    //return;
    
	int xres = GetXRes();
	int yres = GetYRes();
	int start_fb = GetFrameBuffer();
	Image image(xres, yres, start_fb);
	

    //<Scene def. lab3>------------------
    PinHoleCamera pcamera;
    PointLight light;
    //Vector3 lpos;
    Scene scene;
    atTriangle tempTri;

    scene.numLights = 1;
    //light..LoadFromGM(GetLight());
    //scene.pointLights = &light;
    scene.startLightAddr = GetLight();
    //lpos.LoadFromGM(GetLight());
    scene.startMatAddr = GetMaterials();
    pcamera.LoadFromGM(GetCamera());
    scene.startTriAddr = GetStartTriangles();
    scene.numTri = GetNumTriangles();
    scene.bvh_start = GetBVH();
    //-----------------------</Scene def. lab3>
    
    //light.LoadFromGM(scene.startLightAddr);
    //printf("lpos: [%f, %f, %f]\n", light.pos[0], light.pos[1], light.pos[2]);

    int imgSize = xres * yres;
    int subImg = 4;
    int bImgSize = imgSize/subImg;
    //Vector3 des;
    //int nodeID = 0;
    int percent = 0;
    Color res, red;
    red.Set(1.0f, 0.0f, 0.0f);
    for(int pixww = atomicinc(0)*subImg; pixww < imgSize; pixww = atomicinc(0) * subImg)
    //int pixww = 63; //256+512 * 256;
    {
        for(int subPix = 0; subPix<subImg; subPix++)
        {
            int pix = pixww+subPix;
            int ix, iy;
            //ConvertLineIndexToZindexXY(pix, ix, iy);
            ix = pix % xres;
            iy = pix / xres;
            //Ray ray = pcamera.CastRay(pix);
            Ray ray = pcamera.CastRay(ix, iy);
            HitRecord hit;
            hit.Init();
            bool isHit = false;
            
            //isHit = RayTracer::TraceRay(ray, scene, hit);
            isHit = RayTracer::TraceBVH(ray, hit);
            int outpix;
            //outpix = iy * xres + ix;
            outpix = pix;
            if(isHit)
            {
                res = shade(ray, hit, scene);
                image.set(outpix, res);
                
                //image.set(outpix, red);

                //printf("hit.normal[%f, %f, %f]\n", hit.N[0], hit.N[1], hit.N[2]);
                //printf("hit.P[%f, %f, %f]\n", hit.P[0], hit.P[1], hit.N[2]);
                //printf("[%i, %i] isHit\n");
            }else
            {
                image.set(outpix, scene.background);
                //image.set(outpix, red);
            }
    /**
            float pf = static_cast<float>(pix)/static_cast<float>(imgSize) * 100.0f;
            if(static_cast<int>(pf) > percent)
            {
                percent = pf;
                printf("%d ", percent);
            }

            **/
        }
    }

    //printf("\n");
    /**/
}


